package com.cwg.dict.ui.rcp.views;

import java.util.List;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TextCellEditor;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.part.ViewPart;

import com.cwg.dict.model.History;
import com.cwg.dict.service.impl.HistoricalImpl;
import com.cwg.dict.ui.rcp.Activator;

public class HistoryView extends ViewPart {

	private static abstract class TableColumnSorter extends ViewerComparator {
		public static final int	ASC			= 1;

		public static final int	DESC		= -1;

		public static final int	NONE		= 0;

		private TableColumn		column;

		private int				direction	= 0;

		private TableViewer		viewer;

		public TableColumnSorter(TableViewer viewer, TableColumn column) {
			this.column = column;
			this.viewer = viewer;
			this.column.addSelectionListener(new SelectionAdapter() {

				@Override
				public void widgetSelected(SelectionEvent e) {
					if (TableColumnSorter.this.viewer.getComparator() != null) {
						if (TableColumnSorter.this.viewer.getComparator() == TableColumnSorter.this) {
							int tdirection = TableColumnSorter.this.direction;

							if (tdirection == ASC) {
								setSorter(TableColumnSorter.this, DESC);
							} else if (tdirection == DESC) {
								setSorter(TableColumnSorter.this, NONE);
							}
						} else {
							setSorter(TableColumnSorter.this, ASC);
						}
					} else {
						setSorter(TableColumnSorter.this, ASC);
					}
				}
			});
		}

		@Override
		public int compare(Viewer viewer, Object e1, Object e2) {
			return direction * doCompare(viewer, e1, e2);
		}

		public void setSorter(TableColumnSorter sorter, int direction) {
			if (direction == NONE) {
				column.getParent().setSortColumn(null);
				column.getParent().setSortDirection(SWT.NONE);
				viewer.setComparator(null);
			} else {
				column.getParent().setSortColumn(column);
				sorter.direction = direction;

				if (direction == ASC) {
					column.getParent().setSortDirection(SWT.DOWN);
				} else {
					column.getParent().setSortDirection(SWT.UP);
				}

				if (viewer.getComparator() == sorter) {
					viewer.refresh();
				} else {
					viewer.setComparator(sorter);
				}

			}
		}

		protected abstract int doCompare(Viewer TableViewer, Object e1, Object e2);
	}

	private static class TableLabelProvider extends LabelProvider implements ITableLabelProvider {

		@Override
		public Image getColumnImage(Object element, int columnIndex) {
			return null;
		}

		@Override
		public String getColumnText(Object element, int columnIndex) {
			History h = (History) element;
			switch (columnIndex) {
			case 0:
				return h.getWord();
			case 1:
				Map<String, Integer> statistic = Activator.getDefault().getHistorical().statistic();
				if (statistic.containsKey(h.getWord())) {
					return statistic.get(h.getWord()).toString();
				} else {
					return "0";
				}
			case 2:
				return Boolean.toString(h.isFavorite());
			default:
				return "undefined column";
			}
		}

	}

	public final static String	ID	= "com.cwg.dict.HistoryView";

	private TableViewer			viewer;

	@Override
	public void createPartControl(Composite parent) {
		viewer = new TableViewer(parent);
		viewer.setContentProvider(new ArrayContentProvider() {
			@Override
			public Object[] getElements(Object inputElement) {
				List<History> all = (List<History>) inputElement;
				// Using SortedMap to sort and to filter out duplicated word 
				SortedMap<String, History> results = new TreeMap<String, History>();
				for (History each : all) {
					if (!results.containsKey(each.getWord())) {
						results.put(each.getWord(), each);
					}
				}
				return results.values().toArray(new History[results.values().size()]);
			}
		});

		TableLabelProvider tableLabelProvider = new TableLabelProvider();
		viewer.setLabelProvider(tableLabelProvider);
		viewer.setColumnProperties(new String[] { "column1", "column2" });
		viewer.setCellEditors(new CellEditor[] { new TextCellEditor(viewer.getTable()), new TextCellEditor(viewer.getTable()) });

		TableColumn column = new TableColumn(viewer.getTable(), SWT.NONE);
		column.setWidth(100);
		column.setText("word");
		setSortable(viewer, column, 0);

		TableColumn column2 = new TableColumn(viewer.getTable(), SWT.NONE);
		column2.setWidth(100);
		column2.setText("count");
		setSortable(viewer, column2, 1);

		TableColumn column3 = new TableColumn(viewer.getTable(), SWT.NONE);
		column3.setWidth(100);
		column3.setText("favorite");
		setSortable(viewer, column3, 2);

		refresh();
		viewer.getTable().setLinesVisible(true);
		viewer.getTable().setHeaderVisible(true);
		viewer.getTable().setVisible(true);

		MenuManager menuManager = new MenuManager();
		Menu menu = menuManager.createContextMenu(viewer.getTable());
		// Set the MenuManager
		viewer.getTable().setMenu(menu);
		getSite().registerContextMenu(menuManager, viewer);
		// Make the selection available
		getSite().setSelectionProvider(viewer);

	}

	public void refresh() {
		HistoricalImpl historical = Activator.getDefault().getHistorical();
		historical.load();
		viewer.setInput(historical.listLatest(0));
	}

	@Override
	public void setFocus() {
		// do nothing
	}

	private void setSortable(final TableViewer viewer, TableColumn column, final int columnIndex) {
		new TableColumnSorter(viewer, column) {
			@Override
			protected int doCompare(Viewer v, Object e1, Object e2) {
				ITableLabelProvider lp = (ITableLabelProvider) viewer.getLabelProvider();
				if (columnIndex == 1) { // count column
					Integer c1 = new Integer(lp.getColumnText(e1, columnIndex));
					Integer c2 = new Integer(lp.getColumnText(e2, columnIndex));
					return c1.compareTo(c2);
				} else {
					String t1 = lp.getColumnText(e1, columnIndex);
					String t2 = lp.getColumnText(e2, columnIndex);
					return t1.compareTo(t2);
				}
			}
		};
	}

}
